In my previous blog post, I described how I was looking into Jeremy Miller's tools for development. Although I think they are terrific tools and still worthy of a look, I made the decision recently to pivot away from them because:
I recently subscribed to Steve Smith's (aka "Ardalis") Modular Monoliths class on DomeTrain. So far I like the approach that Steve takes on construction of a monolith with different domain areas. What he didn't cover (nor does he need to as it isn't exactly relevant to his topic) is how to get this working in Aspire. There are some Aspire things that I want to incorporate into Steve's model.
This one was fairly simple. You'll want to use the Aspire.NpgSql.EntityFrameworkCore.PostgreSQL
and Npgsql.EntityFrameworkCore.PostgreSQL
NuGet packages in your separate monolith domain projects (like Users). In your AppHost project, you'll want the Aspire.Hosting.PostgreSQL
NuGet package.
In your AppHost Program.cs
file, you'll want to have something like this:
var dbserver = builder.AddPostgres("dbserver")
.WithPgAdmin();
// Keep track of the "yourdb" string - we'll be using it in the Users domain project
var yourDb = dbserver.AddDatabase("yourdb");
Steve recommends creating an Extensions
file in your domain projects that add the explicit services you need in that project. You'll be setting up your DbContext
here and will need the connection string from the AppHost project. This connection string changes every time you start up your solution, so you'll always need to reference it from AppHost by doing this:
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
namespace YourAppName.Users;
// This is the area explicitly setup for Users context
public static class UserServiceExtensions
{
public static IServiceCollection AddUserServices(this IServiceCollection services, IConfiguration configuration)
{ services.AddDbContext<UserDbContext>(options =>
// Make sure that the name you use in the GetConnectionString is the same name you used in AppHost options.UseNpgsql(configuration.GetConnectionString("yourdb")));
services.AddScoped<IUserRepository, EfUserRepository>();
services.AddScoped<IUserService, UserService>();
return services;
}}
Now that we have the connections setup between AppHost and your domain project, we'll tackle setting up migrations.
In our development environment, we want to conduct EF Core data migrations every time the Aspire AppHost is run. This is due to the fact that Docker containers for your database are constructed and destroyed every time you start and stop the application. You'll most likely want sample data deployed to the database every time you start the application so that you can conduct testing against it. The sample on seeding data on the Microsoft Learn site didn't work me, at least the Seed data using Entity Framework Core section. Setting up a MigrationService
project in the solution was an elegant solution to the problem.
Create the project as a Worker
project so that it can be added to your AppHost
project later on. If you edit your .csproj
file, you should see <Project Sdk="Microsoft.NET.Sdk.Worker">
at the top. Your project will depend on two NuGet packages, Microsoft.EntityFrameworkCore
and Npgsql.EnityFrameworkCore.PostgreSQL
. Also make sure that your project references your domain projects so that you can use their DbContext
files in this project.
Your project will have two files in it:
Now every time you deploy and run your app, your database will be setup and ready to go!